package com.fancy.gateway.config;

import com.fancy.gateway.filter.AdminAuthenticationFilter;
import com.fancy.gateway.filter.AuthenticationFilter;
import lombok.RequiredArgsConstructor;
import org.springframework.cloud.gateway.filter.ratelimit.RedisRateLimiter;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;

import java.util.Arrays;

/**
 * 网关配置类
 *
 * @author fancy
 */
@Configuration
@RequiredArgsConstructor
public class GatewayConfig {

    private final AuthenticationFilter authenticationFilter;
    private final AdminAuthenticationFilter adminAuthenticationFilter;
    private final RateLimitConfig rateLimitConfig;

    /**
     * CORS配置
     */
    @Bean
    public CorsWebFilter corsWebFilter() {
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOriginPattern("*");
        config.setAllowedMethods(Arrays.asList(
            HttpMethod.GET.name(),
            HttpMethod.POST.name(),
            HttpMethod.PUT.name(),
            HttpMethod.DELETE.name(),
            HttpMethod.OPTIONS.name()
        ));
        config.setAllowedHeaders(Arrays.asList("*"));
        config.setExposedHeaders(Arrays.asList(
            "Content-Length",
            "Content-Range",
            "Authorization",
            "X-User-Id",
            "X-Username"
        ));

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);

        return new CorsWebFilter(source);
    }

    /**
     * 编程式路由配置（作为YAML配置的补充）
     */
    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
                // 登录和注册路由（不需要认证）
                .route("auth-route", r -> r
                        .path("/api/v1/users/login", "/api/v1/users/register", "/api/v1/auth/**")
                        .filters(f -> f
                                .requestRateLimiter(config -> {
                                    config.setKeyResolver(rateLimitConfig.userKeyResolver());
                                    config.setRateLimiter(redisRateLimiter());
                                })
                                .addRequestHeader("X-Service-Name", "user-service"))
                        .uri("lb://user-service"))

                // 健康检查路由
                .route("health-route", r -> r
                        .path("/actuator/**")
                        .filters(f -> f
                                .requestRateLimiter(config -> {
                                    config.setKeyResolver(rateLimitConfig.ipKeyResolver());
                                    config.setRateLimiter(redisRateLimiter());
                                }))
                        .uri("lb://user-service"))

                // 静态资源路由
                .route("static-route", r -> r
                        .path("/static/**", "/images/**", "/files/**")
                        .filters(f -> f
                                .requestRateLimiter(config -> {
                                    config.setKeyResolver(rateLimitConfig.ipKeyResolver());
                                    config.setRateLimiter(redisRateLimiter());
                                }))
                        .uri("lb://music-service"))

                .build();
    }

    /**
     * Redis限流器配置
     */
    @Bean
    public RedisRateLimiter redisRateLimiter() {
        return new RedisRateLimiter(100, 200, 1);
    }
}
